import os,sys
from common import Tick
import pygame.font
from weapons import *
font_size = 16
bg_color = (0,0,0)
antialias = 1
'In game Menu Objects' 
class MenuAction:
    ' defines MenuAction interface'
    def __init__(self):
        pass
    def action(self,dt):
        pass
    def renderBar(self,viewport,offset,selected,max_width,val,max):
        'Render a bar'
        if selected: color = (255,255,255)
        else:    color = (155,155,055)

        status_w = max_width*0.75
        status_h = font_size/2

        xpos = offset[0]
        ypos = offset[1]+status_h/2
        try:
            viewport.fill((150,150,150),(xpos,ypos,status_w,status_h)) # draw status bar background
            viewport.fill(color,(xpos,ypos,status_w*(val/max),status_h)) # draw status bar 
            #screen.fill((0,0,0),(xpos+status_w*(v.max/max)-1,ypos,1,status_h)) # draw max indication
        except ZeroDivisionError:
            pass

class SetPrimWeapon(MenuAction):
    def __init__(self,player,weapon):
        MenuAction.__init__(self)
        self.player = player
        self.weapon = weapon
    def action(self,dt):
        self.player.ship.prim_weapon    =self.weapon

class SetSecWeapon(MenuAction):
    def __init__(self,player,weapon):
        MenuAction.__init__(self)
        self.player = player
        self.weapon = weapon
    def action(self,dt):
        self.player.ship.sec_weapon    =self.weapon

class SetFuel(MenuAction):
    def __init__(self,player,change_rate=40):
        MenuAction.__init__(self)
        self.player = player
        self.change_rate = change_rate
        self.font = pygame.font.Font(None, font_size)
    def next(self,dt):
        self.player.ship.fuel.max += dt*self.change_rate
        if self.player.ship.fuel.max > self.player.ship.max_fuel:
            self.player.ship.fuel.max = self.player.ship.max_fuel

    def prev(self,dt):
        self.player.ship.fuel.max -= dt*self.change_rate
        if self.player.ship.fuel.max < 0:
            self.player.ship.fuel.max = 0

    def render(self,viewport,offset,selected=0,max_width=100):
        s = self.player.ship
        max = s.max_fuel
        val = s.fuel.max
        self.renderBar(viewport,offset,selected,max_width,val,max)
        
class SetPrimAmmo(MenuAction):
    def __init__(self,player,change_rate=40):
        MenuAction.__init__(self)
        self.change_rate = change_rate
        self.player = player
        self.font = pygame.font.Font(None, font_size)
        self.ammo = 0
    def next(self,dt):
        self.player.ship.prim_weapon.ammo.max += dt*self.change_rate
    def prev(self,dt):
        self.player.ship.prim_weapon.ammo.max -= dt*self.change_rate
        if self.player.ship.prim_weapon.ammo.max < 0:
            self.player.ship.prim_weapon.ammo.max = 0

    def render(self,viewport,offset,selected=0,max_width=100):
        w = self.player.ship.prim_weapon
        max = w.max_ammo
        val = w.ammo.max
        self.renderBar(viewport,offset,selected,max_width,val,max)


class SetSecAmmo(MenuAction):
    def __init__(self,player,change_rate=20):
        MenuAction.__init__(self)
        self.change_rate = change_rate
        self.player = player
        self.font = pygame.font.Font(None, font_size)
        self.ammo = 0
    def next(self,dt):
        self.player.ship.sec_weapon.ammo.max += dt*self.change_rate

    def prev(self,dt):
        self.player.ship.sec_weapon.ammo.max -= dt*self.change_rate
        if self.player.ship.sec_weapon.ammo.max < 0:
            self.player.ship.sec_weapon.ammo.max = 0

    def render(self,viewport,offset,selected=0,max_width=100):
        w = self.player.ship.sec_weapon
        max = w.max_ammo
        val = w.ammo.max
        self.renderBar(viewport,offset,selected,max_width,val,max)
##        self.ammo = self.player.ship.sec_weapon.ammo.max
##        if selected: color = (255,255,255)
##        else:    color = (155,155,155)
##        viewport.blit(self.font.render("Ammo %d"%self.ammo, antialias, color,bg_color), offset)
        

class WeaponSelector:
    ''' Class for handling player docking menu, setting weapons ''' 
    def __init__(self,owner):
        self.font = pygame.font.Font(None, font_size)
        self.owner = owner

        # set main choices
        self.root = Node('root')
        prim_weapons = Node('Primary')
        sec_weapons = Node('Secondary')

        # set up fuel choise
        fuel = Node('Fuel')
        fuel.addChild(Node('Fuel',obj=SetFuel(self.owner)))

        # set up ammo choises
        ammo1 = Node('PrimAmmo')
        ammo1.addChild(Node('Prim_Ammo',obj=SetPrimAmmo(self.owner)))
        ammo2 = Node('SecAmmo')
        ammo2.addChild(Node('Sec_Ammo',obj=SetSecAmmo(self.owner,change_rate=7)))

        # add childnodes to root node        
        self.root.addChild(prim_weapons)
        self.root.addChild(sec_weapons)
        self.root.addChild(fuel)
        self.root.addChild(ammo1)
        self.root.addChild(ammo2)

        # Make weapon menu action objects
        gun = SetPrimWeapon(self.owner,Gun(self.owner))
        trigun = SetPrimWeapon(self.owner,TriGun(self.owner))
        twingun = SetPrimWeapon(self.owner,TwinGun(self.owner))
        sweapgun = SetPrimWeapon(self.owner,SweapGun(self.owner))

        bomber = SetSecWeapon(self.owner,Bomber(self.owner))
        clusterbomber = SetSecWeapon(self.owner,ClusterBomber(self.owner))
        missile = SetSecWeapon(self.owner,Launcher(self.owner))
        mine = SetSecWeapon(self.owner,MineLayer(self.owner))
        proxymine = SetSecWeapon(self.owner,ProxyMineLayer(self.owner))

        # add childnodes to weapons nodes
        prim_weapons.addChild(Node('Gun',gun))
        prim_weapons.addChild(Node('TwinGun',twingun))
        prim_weapons.addChild(Node('TriGun',trigun))
        prim_weapons.addChild(Node('SweapGun',sweapgun))
        sec_weapons.addChild(Node('Bomber',bomber))
        sec_weapons.addChild(Node('ClusterBomber',clusterbomber))
        sec_weapons.addChild(Node('Missile',missile))
        sec_weapons.addChild(Node('Mine',mine))
        sec_weapons.addChild(Node('ProxyMine',proxymine))


        self.node = self.root.childs[0]
        self.key_inverval = Tick(0.2)

    def update(self,dt):
         self.key_inverval.tick(dt)

    def isAtRoot(self):
        return self.node.parent == self.root
    def keyReady(self):
        return self.key_inverval.isSet()
    def reset(self):
        self.key_inverval.reset()
        
    # controller interface methods
    def left(self,dt):    self._prev(dt)
    def right(self,dt):    self._next(dt)
    def up(self,dt):    self._unselect(dt)
    def down(self,dt):    self._unselect(dt)
    def fire1(self,dt):    self._select(dt)
    def fire2(self,dt):    pass

    def _next(self,dt):
        # see if nodes object supports next method if not go to next node
        if hasattr(self.node.obj,"next"):
            self.node.obj.next(dt)
        else:
            if self.node.parent and self.key_inverval.isSet():
                self.key_inverval.reset()
                self.node = self.node.parent.next()

    def _prev(self,dt):
        # see if nodes object supports next method if not go to next node
        if hasattr(self.node.obj,"prev"):
            self.node.obj.prev(dt)
        elif self.key_inverval.isSet() and self.node.parent:
            # if the node is the first go up one step
            if self.node == self.node.parent.first():
                self._unselect(dt)
            else:
                self.node = self.node.parent.prev()
            self.key_inverval.reset()

    def _unselect(self,dt):
        if self.node.parent and self.key_inverval.isSet() \
           and self.node.parent != self.root:        # dont go up to root
            self.key_inverval.reset()
            self.node = self.node.parent

        # change controls
        self._setupControls()

    def _select(self,dt):
        if self.key_inverval.isSet():
            self.key_inverval.reset()
            if self.node.childs:
                self.node = self.node.childs[0] 
            elif self.node.obj:
                self.node.obj.action(dt)
                self.node.parent.sel_child = self.node    
        # change controls
        self._setupControls()

    def _setupControls(self):
        ' ugly hack to get more logical navigation when menu changes from horizintal to vertical or to a value setting node'
        if self.node.parent == self.root or (hasattr(self.node.obj,"next") and hasattr(self.node.obj,"prev")):
            self.left     = self._prev
            self.right    = self._next
            self.up     = self._unselect
            self.down    = self._select
            self.fire1    = self._select
            self.fire2    = self._unselect
        else:
            self.left     = self._unselect
            self.right    = self._unselect
            self.up     = self._prev
            self.down    = self._next
            self.fire1    = self._select
            self.fire2    = self._unselect

    def setup(self):
        ''' Setup the owner with menu defaults '''
        self.root.childs[0].sel_child = self.root.childs[0].childs[0]
        self.root.childs[1].sel_child = self.root.childs[1].childs[0]
        self.root.childs[0].childs[0].obj.action(0)
        self.root.childs[1].childs[0].obj.action(0)
        
    def render(self,viewport):
        ''' Render the players menu '''
        x = 20
        sel_color = (200,55,55)
        def_color = (155,155,155)
        cur_color = (255,255,255)
        for group in self.root.childs:
            y = 20
            if group == self.node:
                viewport.blit(self.font.render(group.name, antialias, (255,255,155),bg_color), (x,y))
            else:
                viewport.blit(self.font.render(group.name, antialias, (155,155,055),bg_color), (x,y))
            for subopt in group.childs:
                y +=  font_size

                # try and see if nodes object renders itself
                if hasattr(subopt.obj,"render"):
                    subopt.obj.render(viewport,(x,y),subopt == self.node,max_width=len(group.name) * font_size)
                else:
                    # else render them here
                    if subopt == self.node:
                        viewport.blit(self.font.render(subopt.name, antialias,cur_color,bg_color), (x,y))
                    elif subopt.parent.sel_child == subopt:
                        viewport.blit(self.font.render(subopt.name, antialias, sel_color,bg_color), (x,y))
                    else:
                        viewport.blit(self.font.render(subopt.name, antialias, def_color,bg_color), (x,y))
            x += len(group.name) * font_size
        

class Node:
    def __init__(self,name,obj=None):
        ' Atomic node that can have child nodes and/or a menu action object '
        self.childs = []
        self.parent = None
        self.childindex = 0
        self.name = name
        self.sel_child = None
        self.obj = obj
    def first(self):
#        self.childindex = 0
        return self.childs[0]
    def last(self):
#        self.childindex = len(self.childs)-1
        return self.childs[len(self.childs)-1]
    def next(self):
        if self.childindex >= len(self.childs)-1: self.childindex = len(self.childs)-1
        else: self.childindex += 1
        return self.childs[self.childindex]
    def prev(self):
        if self.childindex <= 0: self.childindex = 0
        else: self.childindex -= 1
        return self.childs[self.childindex]
    def up(self):
        return self.parent
    def addChild(self,node):
        node.parent = self
        self.childs.append(node)
#------------------------------------------------------------

